/**
 * Copyright (c) 2013 onionframework.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.onionframework.event;

import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.commons.collections4.CollectionUtils;
import org.onionframework.event.SpringEventListenerRegistry.OnionEventListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationAdapter;
import org.springframework.transaction.support.TransactionSynchronizationManager;

/**
 * 事件触发类
 * 
 * @author allan
 *
 */
@Component
public class Events {

	private static final Logger logger = LoggerFactory.getLogger(Events.class);

	@Autowired
	private SpringEventListenerRegistry springEventListenerRegistry;

	@Autowired(required = false)
	private TaskExecutor asyncEventListenerExecutor;
	
	private static Events instance;

	@PostConstruct
	public void init() {
		instance = this;
		if (this.asyncEventListenerExecutor == null)
			this.asyncEventListenerExecutor = new SimpleAsyncTaskExecutor(
					"OnionAsyncEventListener-");
	}

	/**
	 * 发布一个事件，会顺序调用所有的监听器
	 * 
	 * @param type
	 *            事件类型
	 * @param parameters
	 *            要传递给事件监听器的参数
	 */
	public void fire(String type, Object... parameters) {
		
		Set<OnionEventListener> eventListeners = this.springEventListenerRegistry
				.getListeners(type);

		if(CollectionUtils.isEmpty(eventListeners))
			return;
		
		logger.trace("Processing event:" + type);

		for (OnionEventListener listener : eventListeners) {
			listener.onApplicationEvent(parameters);
		}
	}

	/**
	 * 发布一个事件，会异步调用所有的监听器
	 * 
	 * @param type
	 *            事件类型
	 * @param parameters
	 *            要传递给事件监听器的参数
	 */
	public void fireAsynchronous(final String type, final Object... parameters) {
		this.asyncEventListenerExecutor.execute(new Runnable() {
			@Override
			public void run() {
				Events.instance().fire(type, parameters);
			}
		});
	}


	/**
	 * 发布一个事件，会在事务被成功提交之后异步调用所有的监听器
	 * 
	 * @param type
	 *            事件类型
	 * @param parameters
	 *            要传递给事件监听器的参数
	 */
	public void fireOnTransactionSuccess(final String type,
			final Object... parameters) {
		TransactionSynchronizationManager
				.registerSynchronization(new TransactionSynchronizationAdapter() {
					@Override
					public void afterCommit() {
						Events.this.fireAsynchronous(type, parameters);
					}
				});
	}

	/**
	 * 发布一个事件，会在事务完成后（提交或者回滚）提交之后异步调用所有的监听器
	 * 
	 * @param type
	 *            事件类型
	 * @param parameters
	 *            要传递给事件监听器的参数
	 */
	public void fireOnTransactionCompletion(final String type,
			final Object... parameters) {
		TransactionSynchronizationManager
				.registerSynchronization(new TransactionSynchronizationAdapter() {
					@Override
					public void afterCompletion(int status) {
						Events.this.fireAsynchronous(type, parameters);
					}
				});
	}
	
	public static Events instance() {
		return instance;
	}
}
